<?php

namespace App\Http\Controllers\Backstage\System;

use Validator;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Services\MenuPermissionService;
use App\Services\RouteService;
use Illuminate\Validation\Rule;
use App\BaseDictionary;
use App\Route;
use App\MenuPermission;

class PermissionController extends Controller
{
    private $menuPermissionService = null;
    private $routeService = null;

    public function __construct(MenuPermissionService $menuPermissionService,
        RouteService $routeService)
    {
        $this->menuPermissionService = $menuPermissionService;
        $this->routeService = $routeService;
    }

    public function index()
    {
        return view('backstage.system.permission.permission');
    }

    public function getInitTrees()
    {
        return $this->menuPermissionService
            ->getCascadeMenuPermissionByLevel(3);
    }

    public function queryPermissions(Request $request)
    {
        return $this->menuPermissionService
            ->getMenuPermissions($request->all(), [
                MenuPermission::$PERMISSION_TYPE_MENU_GROUP,
                MenuPermission::$PERMISSION_TYPE_MENU,
                MenuPermission::$PERMISSION_TYPE_OPERATION
            ]);
    }

    public function create($parentId)
    {
        $parent = MenuPermission::findOrFail($parentId);

        return view('backstage.system.permission.create', [
            'parent' => $parent,
            'routes' => $this->routeService->getRoutes([
                'routeType'=>Route::$ROUTE_TYPE_WEB
            ], false),
            'parentPermissions' => $this->menuPermissionService->getMenuPermissions(
                [], [$parent->permission_type], false
            )
        ]);
    }

    public function saveNew(Request $request)
    {
        $input = $request->all();

        $parent = MenuPermission::findOrFail($input['parent_id']);

        if ($parent->permission_type == MenuPermission::$PERMISSION_TYPE_TOP_NAVI) {
            $input['permission_type'] = MenuPermission::$PERMISSION_TYPE_MENU_GROUP;
            $input['is_default'] = BaseDictionary::$KEY_NO;
        } else if ($parent->permission_type == MenuPermission::$PERMISSION_TYPE_MENU_GROUP) {
            $input['permission_type'] = MenuPermission::$PERMISSION_TYPE_MENU;
        } else if ($parent->permission_type == MenuPermission::$PERMISSION_TYPE_MENU) {
            $input['permission_type'] = MenuPermission::$PERMISSION_TYPE_OPERATION;
            $input['permission_type'] = MenuPermission::$PERMISSION_TYPE_MENU_GROUP;
            $input['is_default'] = BaseDictionary::$KEY_NO;
        }

        $this->validateWhenSaveNew($input);

        MenuPermission::create($input);

        return response()->json([
            'Success' => true,
            'Message' => '新增权限成功',
        ]);
    }

    public function edit($permissionId)
    {
        $permission = MenuPermission::findOrFail($permissionId);
        $parent = $permission->parent;

        return view('backstage.system.permission.create', [
            'parent' => $parent,
            'routes' => $this->routeService->getRoutes([
                'routeType'=>Route::$ROUTE_TYPE_WEB
            ], false),
            'parentPermissions' => $this->menuPermissionService->getMenuPermissions(
                [], [$parent->permission_type], false
            ),
            'permission' => $permission
        ]);
    }

    public function update(Request $request)
    {
        $input = $request->all();

        $this->validateWhenSaveUpdate($input);

        $permission = MenuPermission::findOrFail($input['id']);
        if (isset($input['route_id'])) {
            $permission->update($input);
        } else {
            $permission->update(array_merge($input,[
                'route_id' => null
            ]));
        }

        return response()->json([
            'Success' => true,
            'Message' => '修改菜单权限成功',
        ]);
    }

    public function delete(Request $request)
    {
        $input = $request->all();

        $this->validateWhenDelete($input);

        $permission = MenuPermission::findOrFail($input['id']);
        $permission->delete();

        return response()->json([
            'Success' => true,
            'Message' => '删除权限成功',
        ]);
    }
    /**
    * 导航权限管理
    */
    public function indexNavi()
    {
        return view('backstage.system.permission.navi_permission');
    }

    public function queryNavi(Request $request)
    {
        return $this->menuPermissionService
            ->getNaviMenuPermissions($request->all());
    }

    public function createNavi()
    {
        return view('backstage.system.permission.create_navi', [
            'routes' => $this->routeService->getRoutes([
                'routeType'=>Route::$ROUTE_TYPE_WEB
            ], false)
        ]);
    }

    public function saveNavi(Request $request)
    {
        $input = $request->all();

        //保存头部导航的权限，除了需要前端传过来的几个字段，还需要增加几个字段
        //使用array_merge合并组合字段
        $input = array_merge($input, [
            'permission_type' => MenuPermission::$PERMISSION_TYPE_TOP_NAVI,
            'is_default' => BaseDictionary::$KEY_NO,
        ]);

        $this->validateWhenSaveNew($input);

        MenuPermission::create($input);

        return response()->json([
            'Success' => true,
            'Message' => '新增头部导航权限成功',
        ]);
    }

    public function editNavi($permissionId)
    {
        return view('backstage.system.permission.create_navi', [
            'routes' => $this->routeService->getRoutes([
                'routeType'=>Route::$ROUTE_TYPE_WEB
            ], false),
            'permission' => MenuPermission::findOrFail($permissionId)
        ]);
    }

    public function updateNavi(Request $request)
    {
        $input = $request->all();

        $input['permission_type'] = MenuPermission::$PERMISSION_TYPE_TOP_NAVI;

        $this->validateWhenSaveUpdate($input);

        $permission = MenuPermission::findOrFail($input['id']);
        if (isset($input['route_id'])) {
            $permission->update($input);
        } else {
            $permission->update(array_merge($input,[
                'route_id' => null
            ]));
        }

        return response()->json([
            'Success' => true,
            'Message' => '修改头部导航权限成功',
        ]);
    }

    public function deleteNavi(Request $request)
    {
        $input = $request->all();

        $this->validateWhenDelete($input);

        $permission = MenuPermission::findOrFail($input['id']);
        $permission->delete();

        return response()->json([
            'Success' => true,
            'Message' => '删除导航权限成功',
        ]);
    }

    /**
    * API权限管理
    */
    public function indexApi()
    {
        return view('backstage.system.permission.api_permission');
    }

    public function queryApi(Request $request)
    {
        return $this->menuPermissionService
            ->getApiPermissions($request->all());
    }

    public function createApi()
    {
        return view('backstage.system.permission.create_api_permission', [
            'routes' => $this->routeService->getRoutes([
                'routeType'=>Route::$ROUTE_TYPE_API
            ], false)
        ]);
    }

    public function saveApi(Request $request)
    {
        $input = $request->all();

        //保存头部导航的权限，除了需要前端传过来的几个字段，还需要增加几个字段
        //使用array_merge合并组合字段
        $input = array_merge($input, [
            'permission_type' => MenuPermission::$PERMISSION_TYPE_API,
            'is_default' => BaseDictionary::$KEY_NO,
        ]);

        $this->validateWhenSaveNew($input);

        MenuPermission::create($input);

        return response()->json([
            'Success' => true,
            'Message' => '新增API导航权限成功',
        ]);
    }

    public function editApi($permissionId)
    {
        return view('backstage.system.permission.create_api_permission', [
            'routes' => $this->routeService->getRoutes([
                'routeType'=>Route::$ROUTE_TYPE_API
            ], false),
            'permission' => MenuPermission::findOrFail($permissionId)
        ]);
    }

    public function updateApi(Request $request)
    {
        $input = $request->all();

        $input['permission_type'] = MenuPermission::$PERMISSION_TYPE_API;

        $this->validateWhenSaveUpdate($input);

        $permission = MenuPermission::findOrFail($input['id']);
        if (isset($input['route_id'])) {
            $permission->update($input);
        } else {
            $permission->update(array_merge($input,[
                'route_id' => null
            ]));
        }

        return response()->json([
            'Success' => true,
            'Message' => '修改API权限成功',
        ]);
    }

    public function deleteApi(Request $request)
    {
        $input = $request->all();

        $this->validateWhenDelete($input);

        $permission = MenuPermission::findOrFail($input['id']);
        $permission->delete();

        return response()->json([
            'Success' => true,
            'Message' => '删除API权限成功',
        ]);
    }

    private function validateWhenSaveNew(Array $input)
    {
        return Validator::make($input, [
            'name' => [
                'required',
                'max:50',
                Rule::unique('menu_permissions')->where(function ($query) use($input) {
                    //同样类型的权限不可重复，但是menu_permissions表里其它的权限类型的名称与其相同不受影响
                    $query->where('name', $input['name'])
                        ->where('permission_type', $input['permission_type']);

                    //如果是菜单组，菜单或者菜单功能权限，那么只需要在相同的父级下不重复即可
                    if ($input['permission_type'] === MenuPermission::$PERMISSION_TYPE_MENU_GROUP ||
                        $input['permission_type'] === MenuPermission::$PERMISSION_TYPE_MENU ||
                        $input['permission_type'] === MenuPermission::$PERMISSION_TYPE_OPERATION) {
                        $query->where('parent_id', $input['parent_id']);
                    }
                })
            ],
            'icon' => 'max:200',
            'route_id' => 'exists:routes,id'.($input['permission_type'] === MenuPermission::$PERMISSION_TYPE_API ||
                $input['permission_type'] === MenuPermission::$PERMISSION_TYPE_MENU ||
                $input['permission_type'] === MenuPermission::$PERMISSION_TYPE_OPERATION ?
                    '|required':''),
            'sort_order' => 'required|numeric',
            'parent_id' => 'exists:menu_permissions,id'.($input['permission_type'] === MenuPermission::$PERMISSION_TYPE_MENU_GROUP ||
                $input['permission_type'] === MenuPermission::$PERMISSION_TYPE_MENU ||
                $input['permission_type'] === MenuPermission::$PERMISSION_TYPE_OPERATION ?
                    '|required':'')
        ], $this->getValidateMessagesWhenSaveNew($input['permission_type']))->validate();
    }

    private function getValidateMessagesWhenSaveNew($permissionType)
    {
        if ($permissionType == MenuPermission::$PERMISSION_TYPE_TOP_NAVI) {
            $nameUnique = '已经存在其它的同名导航名称';
        } else if ($permissionType == MenuPermission::$PERMISSION_TYPE_MENU_GROUP) {
            $nameUnique = '已经存在相同的导航下的其它的同名菜单组权限名称';
        } else if ($permissionType == MenuPermission::$PERMISSION_TYPE_MENU) {
            $nameUnique = '已经存在相同的菜单组下的其它的同名菜单权限名称';
        } else if ($permissionType == MenuPermission::$PERMISSION_TYPE_OPERATION) {
            $nameUnique = '已经存在相同的菜单下的其它的同名菜单操作权限名称';
        } else if ($permissionType == MenuPermission::$PERMISSION_TYPE_API) {
            $nameUnique = '已经存在其它的同名API权限名称';
        }
        return [
            'name.required' => '名称必须存在',
            'name.max'  => '名称长度不可超过:max',
            'name.unique' => $nameUnique,
            'icon.max'  => '图标长度不可超过:max',
            'route_id.exists' => '路由id不存在',
            'sort_order.required' => '排序号必须存在',
            'sort_order.numeric' => '排序号必须是数字',
            'parent_id.exists' => '传入的父级权限id在系统中不存在',
            'parent_id.required' => '父级权限id必须存在',
        ];
    }

    private function validateWhenSaveUpdate(Array $input) {
        return Validator::make($input, [
            'name' => [
                'required',
                'max:50',
                Rule::unique('menu_permissions')->where(function ($query) use($input) {
                    //头部导航权限不可重复，但是menu_permissions表里其它的权限类型的名称与其相同不受影响
                    $query->where('name', $input['name'])
                        ->where('permission_type', $input['permission_type'])
                        ->where('id', '<>', $input['id']);

                    //如果是菜单组，菜单或者菜单功能权限，那么只需要在相同的父级下不重复即可
                    if ($input['permission_type'] === MenuPermission::$PERMISSION_TYPE_MENU_GROUP ||
                        $input['permission_type'] === MenuPermission::$PERMISSION_TYPE_MENU ||
                        $input['permission_type'] === MenuPermission::$PERMISSION_TYPE_OPERATION) {
                        $query->where('parent_id', $input['parent_id']);
                    }
                })
            ],
            'icon' => 'max:200',
            'route_id' => 'exists:routes,id'.($input['permission_type'] === MenuPermission::$PERMISSION_TYPE_API ||
                $input['permission_type'] === MenuPermission::$PERMISSION_TYPE_MENU ||
                $input['permission_type'] === MenuPermission::$PERMISSION_TYPE_OPERATION ?
                    '|required':''),
            'sort_order' => 'required|numeric',
            'parent_id' => 'exists:menu_permissions,id'.($input['permission_type'] === MenuPermission::$PERMISSION_TYPE_MENU_GROUP ||
                $input['permission_type'] === MenuPermission::$PERMISSION_TYPE_MENU ||
                $input['permission_type'] === MenuPermission::$PERMISSION_TYPE_OPERATION ?
                    '|required':'')
        ], $this->getValidateMessagesWhenSaveUpdate($input['permission_type']))->validate();
    }

    private function getValidateMessagesWhenSaveUpdate($permissionType)
    {
        if ($permissionType == MenuPermission::$PERMISSION_TYPE_TOP_NAVI) {
            $nameUnique = '已经存在其它的同名导航名称';
        } else if ($permissionType == MenuPermission::$PERMISSION_TYPE_MENU_GROUP) {
            $nameUnique = '已经存在相同的导航下的其它的同名菜单组权限名称';
        } else if ($permissionType == MenuPermission::$PERMISSION_TYPE_MENU) {
            $nameUnique = '已经存在相同的菜单组下的其它的同名菜单权限名称';
        } else if ($permissionType == MenuPermission::$PERMISSION_TYPE_OPERATION) {
            $nameUnique = '已经存在相同的菜单下的其它的同名菜单操作权限名称';
        } else if ($permissionType == MenuPermission::$PERMISSION_TYPE_API) {
            $nameUnique = '已经存在其它的同名API权限名称';
        }

        return [
            'name.required' => '名称必须存在',
            'name.max'  => '名称长度不可超过:max',
            'name.unique' => $nameUnique,
            'icon.max'  => '图标长度不可超过:max',
            'route_id.exists' => '路由id不存在',
            'sort_order.required' => '排序号必须存在',
            'sort_order.numeric' => '排序号必须是数字',
            'parent_id.exists' => '传入的父级权限id在系统中不存在',
            'parent_id.required' => '父级权限id必须存在',
        ];
    }

    private function validateWhenDelete(Array $input)
    {
        return Validator::make($input, [
                'id' => 'required|exists:menu_permissions,id'
            ], [
                'id.required' => '必须传入权限ID',
                'id.exists' => '该权限ID参数有误，权限不存在'
            ])->after(function ($validator) use($input) {
                if ($this->menuPermissionService->hasChildren($input['id'])) {
                    $validator->errors()->add('id', '该权限存在子权限，不可删除');
                }
                if ($this->menuPermissionService->hasConstrait($input['id'])) {
                    $validator->errors()->add('id', '该权限已经被分配到了某些角色中，不可删除');
                }
            })->validate();
    }
}
